{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "12058891",
   "metadata": {},
   "source": [
    "\n",
    "# 采用变分算法重构普适双比特门\n",
    "\n",
    "尝试采用两个 CNOT 门构建，发现这是不可以的。\n",
    "\n",
    "变分线路构建"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "dedea826",
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1/10   acc: 0.9975399483153466\n",
      "2/10   acc: 0.9859606641409581\n",
      "3/10   acc: 0.9970366827132137\n",
      "4/10   acc: 0.9466270623847457\n",
      "5/10   acc: 0.9994909995547852\n",
      "6/10   acc: 0.9513061070991679\n",
      "7/10   acc: 0.9838905556590538\n",
      "8/10   acc: 0.9945475024451836\n",
      "9/10   acc: 0.9397806431018944\n",
      "10/10   acc: 0.9994736313386009\n",
      "\n",
      "平均保真度为： 0.979565379675295\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "from mindquantum import *\n",
    "from scipy.linalg import expm\n",
    "import mindspore as ms\n",
    "from mindspore import ops\n",
    "ms.context.set_context(mode=ms.context.PYNATIVE_MODE, device_target=\"CPU\")\n",
    "from mindspore.nn import Adam, TrainOneStepCell\n",
    "from mindspore.common.parameter import Parameter\n",
    "from mindspore.common.initializer import initializer  \n",
    "ms.set_seed(1)\n",
    "np.random.seed(1)\n",
    "\n",
    "train_x = np.load('./src/2_qubit_train_x.npy', allow_pickle=True)\n",
    "eval_x = np.load('./src/2_qubit_eval_x.npy', allow_pickle=True)\n",
    "train_y = np.load('./src/2_qubit_train_y.npy', allow_pickle=True)\n",
    "eval_y = np.load('./src/2_qubit_eval_y.npy', allow_pickle=True)\n",
    "u_mats = np.load('./src/2_qubit_u.npy', allow_pickle=True)\n",
    "\n",
    "s_x = X.matrix()\n",
    "s_z = Z.matrix()\n",
    "\n",
    "circ = Circuit()\n",
    "circ += U3('00','01','02', 0)\n",
    "circ += U3('10','11','12', 1)\n",
    "circ += X.on(1,0)\n",
    "circ += U3('03','04','05', 0)\n",
    "circ += U3('13','14','15', 1)\n",
    "circ += X.on(0,1)\n",
    "circ += U3('06','07','08', 0)\n",
    "circ += U3('16','17','18', 1)\n",
    "# circ += X.on(1,0)\n",
    "# circ += U3('09','010','011', 0)\n",
    "# circ += U3('19','110','111', 1)\n",
    "\n",
    "ham = Hamiltonian(QubitOperator('')) \n",
    "sim = Simulator('projectq', circ.n_qubits)\n",
    "sim_left = Simulator('projectq',circ.n_qubits)\n",
    "\n",
    "grad_ops = sim.get_expectation_with_grad(ham,\n",
    "                                         circ,\n",
    "                                         circ_left=Circuit(),\n",
    "                                         simulator_left=sim_left,\n",
    "                                         ansatz_params_name=circ.params_name)\n",
    "\n",
    "class MQLayer(ms.nn.Cell):\n",
    "    def __init__(self, expectation_with_grad, weight='normal'):\n",
    "        super(MQLayer, self).__init__()\n",
    "        self.evolution = MQN2Ops(expectation_with_grad)\n",
    "        weight_size = len(self.evolution.expectation_with_grad.ansatz_params_name)\n",
    "        self.weight = Parameter(initializer(weight,\n",
    "                                            weight_size,\n",
    "                                            dtype=ms.float32),\n",
    "                                name='ansatz_weight')\n",
    "\n",
    "    def construct(self, x, y):\n",
    "        return self.evolution(self.weight, x, y)\n",
    "    \n",
    "\n",
    "acc_list = []\n",
    "for i in range(len(u_mats)):\n",
    "    QuantumNet = MQLayer(grad_ops)\n",
    "    opti = Adam(QuantumNet.trainable_params(), learning_rate=0.02)     \n",
    "    net = TrainOneStepCell(QuantumNet, opti)\n",
    "    \n",
    "    for j in range(len(train_x)):\n",
    "        res = net(ms.Tensor(train_x[j]), ms.Tensor(train_y[i,j]))\n",
    "        \n",
    "    final_state = []\n",
    "    for j in range(len(eval_x)):\n",
    "        sim.reset()\n",
    "        sim.set_qs(eval_x[j])\n",
    "        sim.apply_circuit(circ, QuantumNet.weight.asnumpy())\n",
    "        final_state.append(sim.get_qs())\n",
    "        \n",
    "    acc = np.real(np.mean([np.abs(np.vdot(bra, ket)) for bra, ket in zip(np.array(final_state), eval_y[i])]))\n",
    "    acc_list.append(acc)\n",
    "    print(f'{i+1}/{len(u_mats)}', '  acc:', acc)\n",
    "    \n",
    "print('\\n平均保真度为：', np.mean(acc_list))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
